import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import { getFileReaderPromise } from '../file';
import downloadFileReturnBuffer from './downloadFileReturnBuffer';

/**
 * @description: 服务端返回ArrayBuffer，前端需要解析
 * @param {AxiosRequestConfig} axiosRequestConfig 默认method POST，headers添加了requestId，responseType arrayBuffer
 * @return {*}
 *  - 成功：{ response, data }
 *  - 失败：请求失败，返回error
 */
export default async function arrayBufferRequest<T = void>(
  url: string,
  axiosRequestConfig: AxiosRequestConfig,
): Promise<{
  response: AxiosResponse<ArrayBuffer>;
  data:
    | {
        type: 'json';
        data: T;
        msg: string;
        ret: number;
      }
    | {
        type: 'file';
        filename?: string;
        url?: string;
        blob: Blob;
      };
}> {
  let response: AxiosResponse<any>;
  try {
    response = await downloadFileReturnBuffer(url, axiosRequestConfig);
  } catch (error: any) {
    // 请求失败了，返回异常
    throw error;
  }
  // 获取响应中的data和headers
  const { data, headers } = response;
  // const data = new ArrayBuffer(0);
  const blob = new Blob([data], { type: 'text/plain;charset=UTF-8' });
  // data json或者file的ArrayBuffer，把arrayBuffer转换为字符串
  const [dataString] = await getFileReaderPromise<string>((fileReader) => {
    fileReader.readAsText(blob);
  });
  // parse 一下，成功了说明返回的是：json | 空的ArrayBuffer，失败返回的是文件
  try {
    const dataObject = JSON.parse(dataString);
    // 这里不做错误判断，只返回格式化的响应
    return {
      response,
      data: {
        ...(dataObject as { data: T; msg: string; ret: number }),
        type: 'json',
      },
    };
  } catch (error) {
    let fileUrl: string | undefined = undefined;
    if (data.byteLength) {
      // 生成带错误信息的文件url
      [fileUrl] = await getFileReaderPromise<string>((fileReader) => {
        fileReader.readAsDataURL(blob);
      });
    }
    // 获取文件名称
    const filename = decodeURI(headers['content-disposition']?.split('=')[1]);
    return {
      response,
      data: {
        filename,
        url: fileUrl,
        blob,
        type: 'file',
      },
    };
  }
}
